'''
Created on Sep 22, 2013

@author: dewey
'''
import os
import tempfile
import copy
import filelib.kml as kml
from xml.sax import SAXException
from maplayers import MapFrameLayer, LineStringLayer, PolygonLayer, ItemizedPointLayer, BitmapLayer
from PyQt4.QtCore import QString

class KMLConvertError(Exception):
    pass
        
def _parsekmlfeature(childobj, targetpoint=None, targetlinestring=None, targetpolygon=None, recursive=False):
    if isinstance(childobj, kml.KMLContainer) and recursive:
        for childchildobj in childobj.childobjs:
            _parsekmlfeature(childchildobj, targetpoint, targetlinestring, targetpolygon, True)
    elif isinstance(childobj, kml.KMLPlacemark):
        if childobj.geometry:
            if childobj.extendedData is not None:
                featuredata = copy.deepcopy(childobj.extendedData.data)
            else:
                featuredata = {}
            if kml.KMLFeature.TAG_NAME in childobj.childtags:
                featuredata[MapFrameLayer.FIELD_NAME] = childobj.childtags[kml.KMLFeature.TAG_NAME]
            if kml.KMLFeature.TAG_DESCRIPTION in childobj.childtags:
                featuredata[MapFrameLayer.FIELD_DESCRIPTION] = childobj.childtags[kml.KMLFeature.TAG_DESCRIPTION]
                    
            if childobj.geometry.tag == kml.KMLGeometry.TAG_POINT and targetpoint:
                point = childobj.geometry.geometryData
                itemId = targetpoint.addPoint(point)
                targetpoint.data[itemId] = copy.deepcopy(featuredata)
            elif childobj.geometry.tag == kml.KMLGeometry.TAG_LINESTRING and targetlinestring:
                pointseries = childobj.geometry.geometryData
                itemId = targetlinestring.addPointSeries(pointseries)
                targetlinestring.data[itemId] = copy.deepcopy(featuredata)
            elif childobj.geometry.tag == kml.KMLGeometry.TAG_POLYGON and targetpolygon:
                polygon = childobj.geometry.geometryData
                itemId = targetpolygon.addPolygon(polygon)
                targetpolygon.data[itemId] = copy.deepcopy(featuredata)
                    
def parseToLayer(filename, layer):
    try:
        document = kml.parse(filename)
        if isinstance(layer, LineStringLayer):
            _parsekmlfeature(document.rootObject, targetlinestring=layer, recursive=True)
        elif isinstance(layer, PolygonLayer):
            _parsekmlfeature(document.rootObject, targetpolygon=layer, recursive=True)
        elif isinstance(layer, ItemizedPointLayer):
            _parsekmlfeature(document.rootObject, targetpoint=layer, recursive=True)
        else:
            raise KMLConvertError, "invalid layer provided to parseToLayer"
        layer.populateFields()
    except IOError:
        raise KMLConvertError, "IO error in parseToLayer"
    except SAXException:
        raise KMLConvertError, "XML error reading document"

def bitmapLayerToFolder(layer, tmpdir, resources, namefield=None, descfield=None, folder=None):
    if not folder:
        folder = kml.KMLContainer(kml.KMLContainer.TAG_FOLDER)
        if layer.name():
            folder.childtags[kml.KMLContainer.TAG_NAME] = layer.name()
        else:
            folder.childtags[kml.KMLContainer.TAG_NAME] = layer.layerId()

    if isinstance(layer, BitmapLayer):            
        geomfunc = lambda itemId: layer.bounds[itemId]
    else:
        raise KMLConvertError, "layer not a bitmap layer"
    
    for itemId in layer.idsList:
        bounds = geomfunc(itemId)
        pm = kml.KMLGroundOverlay()
        latlonbox = kml.KMLLatLonBox()
        latlonbox.setBounds(bounds)
        pm.setLatLonBox(latlonbox)
        
        tmpimage = tempfile.mkstemp(suffix=".png", dir=tmpdir)[1]
        if layer.pixmaps[itemId].toImage().save(QString(tmpimage)):
            resources[os.path.basename(tmpimage)] = tmpimage
            pm.setResource(os.path.basename(tmpimage))
            
            named = False
            desced = False
            if itemId in layer.data:
                itemData = layer.data[itemId]
                if namefield in itemData:
                    pm.childtags[kml.KMLPlacemark.TAG_NAME] = unicode(itemData[namefield])
                    named = True
                    
                if descfield in itemData:
                    pm.childtags[kml.KMLPlacemark.TAG_DESCRIPTION] = unicode(itemData[descfield])
                    desced = True
                
                extendedData = kml.KMLExtendedData(itemData)
                pm.setExtendedData(extendedData)
            
            if not named:
                pm.childtags[kml.KMLPlacemark.TAG_NAME] = layer.itemName(itemId)
            if not desced:
                description = layer.itemDescription(itemId)
                if description:
                    pm.childtags[kml.KMLPlacemark.TAG_DESCRIPTION] = description
            
            folder.childobjs.append(pm)
        else:
            print "error saving image!", itemId
    
    return folder

def layerToFolder(layer, namefield=None, descfield=None, folder=None):
    if not folder:
        folder = kml.KMLContainer(kml.KMLContainer.TAG_FOLDER)
        if layer.name():
            folder.childtags[kml.KMLContainer.TAG_NAME] = layer.name()
        else:
            folder.childtags[kml.KMLContainer.TAG_NAME] = layer.layerId()

    if isinstance(layer, ItemizedPointLayer):            
        geomfunc = lambda itemId: layer.points[itemId]
    elif isinstance(layer, LineStringLayer):
        geomfunc = lambda itemId: layer.pointSeries[itemId]
    elif isinstance(layer, PolygonLayer):
        geomfunc = lambda itemId: layer.polygons[itemId]
    else:
        raise KMLConvertError, "layer not of convertable type"
    
    for itemId in layer.idsList:
        geometry = geomfunc(itemId)
        pm = kml.KMLPlacemark()
        kmlgeom = kml.KMLGeometry(geometryData=geometry)
        pm.setGeometry(kmlgeom)
        
        named = False
        desced = False
        if itemId in layer.data:
            itemData = layer.data[itemId]
            if namefield in itemData:
                pm.childtags[kml.KMLPlacemark.TAG_NAME] = unicode(itemData[namefield])
                named = True
                
            if descfield in itemData:
                pm.childtags[kml.KMLPlacemark.TAG_DESCRIPTION] = unicode(itemData[descfield])
                desced = True
            
            extendedData = kml.KMLExtendedData(itemData)
            pm.setExtendedData(extendedData)
        
        if not named:
            pm.childtags[kml.KMLPlacemark.TAG_NAME] = layer.itemName(itemId)
        if not desced:
            description = layer.itemDescription(itemId)
            if description:
                pm.childtags[kml.KMLPlacemark.TAG_DESCRIPTION] = description
        folder.childobjs.append(pm)  
    
    return folder
    
if __name__ == "__main__":
    layer = PolygonLayer("kmllayer1")
    parseToLayer("/Users/dewey/Desktop/testkml.kml", layer)
    print layer
    folder = layerToFolder(layer)
    print folder
    